import axios from 'axios'
import { MessageBox, Message } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'
import i18n from "@/assets/lang"

let flag = false;
let refresh = false;
// 闭包 单例的 全局只有一个
function abstinence (duration){
  let timer = null;
  return ()=> {
    if(timer){
      return
    }
    timer = setTimeout(()=> {
      clearTimeout(timer)
      timer = null
    }, duration)
    Message({
      type: "error",
      message: i18n.t("notification.neterr"),
      showClose: true,
    })
  }
}
// 单例 abstinence
let networkErr = abstinence(30000)
// create an axios instance
// 根据不同的情况和功能业务场景  创建多个不同的axios实例
// 动态传入参数创建axios实例 然后再发送请求
const service = axios.create({
  // 开发环境跨域与生产环境 仅仅是protocol, host, port, baseRoute的不同
  // 只需要修改基路径即可
  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  withCredentials: false, // 携带凭证 cookie
  // timeout: 5000, // request timeout
  // `transformRequest` 允许在向服务器发送前，修改请求数据
  // 只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法
  // 后面数组中的函数必须返回一个字符串，或 ArrayBuffer，或 Stream
  // transformRequest: [(data, headers) => {
  //   // 对data进行转换处理 对请求体的数据进行处理
  //   if(data) {
  //     data.eccess_token = getToken()
  //     console.log(data)
  //   }
  //   return data
  // }]
})

// request interceptor
service.interceptors.request.use(
  config => {
    /**
     * 请求切面配置
     * 拦截所有axios请求 在请求发出去之前做统一的全局配置
     * vuex getters 有坑 慎用 最好直接使用state
     */
    const token = store.state.user.token
    if (true) {
      // config.headers['X-Token'] = getToken()
      if(config.method=='get'){
        if(config.params){
          // config.params.static == true ? delete config.params.static : config.params.access_token = token
          config.params.access_token = token
        } else {
          config.params = { access_token: token }
        }
      } else if (config.method == "post") {
        // console.log(config.data)
        // if(config.data){
        //   config.data.access_token = token
        // } else {
        //   config.data = { access_token : token }
        // }
        // post请求可以有params queryString 和 data request payload
        if(config.params){
          config.params.access_token = token
          // config.params.access_token = store.getters.token
        } else {
          config.params = { access_token: token }
        }
      }
    }
    return config
  },
  error => {
    // do something with request error
    // network error proxy error
    if(store.state.info.showModal){
      return Promise.reject({code: "-8"})
    }
    console.log(error, '请求出错') // for debug
    networkErr()
    // 网络错误  登录页需要处理
    error.code = 10
    return Promise.reject(error)  // 回调promise的catch函数
  }
)

// response interceptor
service.interceptors.response.use(
  /**
   * If you want to get http information such as headers or status
   * Please return  response => response
  */

  /**
   * Determine the request status by custom code
   * Here is just an example
   * You can also judge the status by HTTP Status Code
   */
  /**
   * proxy 代理 + ASP 面向切面 和 切入点
   * before  after  认证授权 控制器 安全 日志输出 测试
   * 收到响应后对返回结果做统一处理
   * 结果返回数据 axios包装过
   * 判断code, message, reason字段
   */
  async response => {

    const { data: res } = response
    // console.log(response.data.code)
    // console.log(JSON.stringify(res))
    // console.dirxml(response)
    if(res.code == '1' || res.code == undefined || res == undefined){
      // await
      // MessageBox.confirm(i18n.t("notification.tokenTimeout"), {
      //   title: i18n.t("messageBox.title.info"),
      //   type: "error", // 同iconClass 比其优先级低
      //   showClose: true,
      //   // center: true,
      //   confirmButtonText: i18n.t("btn.confirm"),
      //   cancelButtonText: i18n.t("btn.cancel"),
      // })
      // Promise的catch必须处理 否则不会往下走
      return Promise.resolve(res)
    } else {
      console.log(res)
      switch(res.code) {
        case "-1" :
          if(refresh){
            return Promise.reject(res)
          }
          refresh = true
          MessageBox.confirm(i18n.t("notification.tokenTimeout"), {
            title: i18n.t("messageBox.title.info"),
            type: "error", // 同iconClass 比其优先级低
            showClose: true,
            // center: true,
            confirmButtonText: i18n.t("btn.confirm"),
            cancelButtonText: i18n.t("btn.cancel"),
          }).then(res=> {
            // token 过期 清空token 刷新页面
            // logout signout signin
            refresh = false
            store.dispatch('user/logout').then(() => {
              location.reload()
            })
          }).catch(err => {
            refresh = false
          }).finally(() => {
            return Promise.reject(res)
          })
        default :
          return Promise.reject(res)
      }

      // Message({
      //   message: res.reason || 'Error',
      //   // message: '走这里',
      //   type: 'error',
      //   duration: 5 * 1000
      // })
      // switch(res.code){
      //   case '-4' || 4 :
      //     return Promise.reject('input_err')
      //     break
      // }
    }

    // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
    // if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
    //   // to re-login
    //   MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
    //     confirmButtonText: 'Re-Login',
    //     cancelButtonText: 'Cancel',
    //     type: 'warning'
    //   }).then(() => {
    //     store.dispatch('user/resetToken').then(() => {
    //       location.reload()
    //     })
    //   })
    // }
  },
  error => {
    if(store.state.info.showModal){
      return Promise.reject({code: "-8"})
    }
    console.log('err' + error) // for debug
    // if(flag == false){
    //   Message({
    //     // message: error.message,
    //     message: i18n.t("notification.neterr"),
    //     type: 'error',
    //     duration: 5 * 1000,
    //     showClose: true,
    //   })
    //   flag = true
    //   setTimeout(()=> {
    //     flag = false
    //   }, 20000)
    // }
    networkErr()
    error.code = 10
    return Promise.reject(error)
  }
)

export default service
